package com.apestech.framework.xml.condition.modul;

import com.apestech.formwork.condition.ConditionUtil;
import com.apestech.framework.db.SqlSession;
import com.apestech.framework.dictionary.modul.Table;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.StringUtil;
import com.apestech.framework.util.callback.SpiltStrCallback;
import com.apestech.framework.xml.table.modul.Tables;
import java.util.ArrayList;

/**
 * @author hup
 * @create 2019-03-05-9:18
 */
public class Account extends ConditionUtil {

    private JSONObject materTable=new JSONObject();

    public class Update {
        private String field;
        private String trigger;
        private String result;

        public void setUpdate(JSONObject map){
            field=map.getString("field");
            trigger=map.getString("trigger");
            result=map.getString("result");
        }

        public String getField() {
            return field;
        }

        public String getTrigger() {
            return trigger;
        }

        public String getResult() {
            return result;
        }
    }

    public class Execute {
        private String api;
        private JSONObject var;

        public void setExecute(JSONObject map){
            api=map.getString("api");
            map.remove("api");
            map.remove("id");
            var=new JSONObject();
            var.putAll(map);
        }

        public String getVarExpress(String id){
            if(var.get(id)==null)  return null;
            return var.getString(id);
        }

        public ArrayList<String> getVarList(){
            return var.getKeylist();
        }

        public String getApi() {
            return api;
        }
    }

    public class Bill {
        private String master;
        private JSONObject field=new JSONObject();
        private Tables table;
        private String msg;

        public void setBill(JSONObject map) throws Exception {
            master=map.getString("master");
            msg=map.getString("msg");
        }

        public void setUpdateTable(JSONObject map) throws Exception {
            String update=map.getString("update");
            UpdateTable updateTable=null;
            if(field.get(update)==null) updateTable=new UpdateTable();
            updateTable.setUpdateTable(map);
            field.put(update, updateTable);
        }

        public void setUpdateTable(UpdateTable updateTable){
            field.put(updateTable.getUpdate(), updateTable);
        }

        public UpdateTable getUpdateTable(String update){
            if(field.get(update)==null) return null;
            return (UpdateTable) field.get(update);
        }

        public ArrayList<String> getTableList() {
            return field.getKeylist();
        }

        public String getMaster() {
            return master;
        }

        public Tables getTable() {
            return table;
        }

        public void setTable(Tables table) {
            this.table = table;
            if(table!=null) materTable.put(id, table.getMasterTableId());
        }

        public String getMsg() {
            if(msg==null) msg="";
            return msg;
        }
    }

    public class UpdateTable {
        private String update;
        private String keyField;
        private ArrayList<String> fields=new ArrayList<String>();
        private String field;
        private JSONObject execute=new JSONObject();
        private String billTableName;
        private BillTable billTable;

        public void setUpdateTable(JSONObject map) throws Exception {
            update=map.getString("update");
            keyField=map.getString("keyField");
            field=map.getString("fields");
            if(keyField!=null) fields.add(keyField);
            if(field!=null){
                execSplitStr(field, ",", new SpiltStrCallback(){
                    @Override
                    public void exec(String id) throws Exception {
                        fields.add(id);
                    }
                });
            }
        }

        public void addExecute(JSONObject map){
            String id=map.getString("id");
            Execute exec= (Execute) execute.get(id);
            if(exec==null) exec=new Execute();
            exec.setExecute(map);
            execute.put(id, exec);
        }

        public Execute getExecute(String id){
            if(execute.get(id)==null) execute.put(id, new Execute());
            return (Execute) execute.get(id);
        }

        public String getKeyField() {
            return keyField;
        }

        public String getUpdate() {
            return update;
        }

        public ArrayList<String> getFields() {
            return fields;
        }

        public String getField() {
            return field;
        }

        public String getBillTableName() {
            return billTableName;
        }

        public void setBillTableName(String billTableName) {
            this.billTableName = billTableName;
        }

        public BillTable getBillTable() {
            return billTable;
        }

        public void setBillTable(BillTable billTable) {
            this.billTable = billTable;
        }
    }

    private SqlSession session;
    private String id;
    private String conditionStrategy;
    private JSONObject bill=new JSONObject();
    private JSONObject update=new JSONObject();
    private Condition condition;
    private ConditionStrategy.Step step;
    private JSONObject updateTable=new JSONObject();

    public Account(SqlSession session){
        this.session=session;
    }

    public void setAccount(JSONObject map){
        id=map.getString("id");
        conditionStrategy=map.getString("conditionStrategy");
    }

    public String getId() {
        return id;
    }

    public String getConditionStrategy() {
        return conditionStrategy;
    }

    public Condition getConditon() {
        return condition;
    }

    public void setConditon(Condition condition) {
        this.condition = condition;
    }

    public ConditionStrategy.Step getStep() {
        return step;
    }

    public void setStep(ConditionStrategy.Step step) {
        this.step = step;
    }

    public void addUpdate(JSONObject map){
        String field=map.getString("field");
        Update u=getUpdate(field);
        u.setUpdate(map);
        update.put(field, u);
    }

    public Update getUpdate(String field){
        Update u= (Update) update.get(field);
        if(u==null){
            u=new Update();
            update.put(field, u);
        }
        return u;
    }

    public ArrayList<String> getUpdateField(){
        return update.getKeylist();
    }

    public void addUpdateTable(String id, JSONObject map) throws Exception {
        String update=map.getString("update");
        Bill b=getBill(id);
        b.setUpdateTable(map);
        updateTable.put(update, id);
        bill.put(id, b);
    }

    public void setBill(JSONObject map) throws Exception {
        String id=map.getString("id");
        Bill b=getBill(id);
        b.setBill(map);
        bill.put(id, b);
    }

    public void setBill(String id, Bill b){
        bill.put(id, b);
    }

    public void addExecute(String id, String update, JSONObject map){
        Bill b=getBill(id);
        b.getUpdateTable(update).addExecute(map);
        bill.put(id, b);
    }

    public Execute getExecute(String id, String update, String execId){
        Bill b=getBill(id);
        return b.getUpdateTable(update).getExecute(execId);
    }

    public Bill getBill(String id){
        Bill b=(Bill) bill.get(id);
        if(b==null){
            b=new Bill();
            bill.put(id, b);
        }
        return b;
    }

    public ArrayList<String> getBillKey(){
        return bill.getKeylist();
    }

    public ArrayList<String> getUpdateKey(){
        return update.getKeylist();
    }

    public void createBillExtandTable(Bill b, String update) throws Exception {
        if(b.getUpdateTable(update).getBillTableName()!=null) return;
        BillTable billTable=b.getUpdateTable(update).getBillTable();
        if(billTable==null) throw new Exception("表名不合法，请检查配置信息！");
        if(billTable.getOper()==null){
            String updateTable=update+"_"+billTable.getOrder();
            b.getUpdateTable(update).setBillTableName(updateTable);
            return;
        }
        Table table=session.getDictTable(b.getUpdateTable(update).getUpdate());
        if(table==null) throw new Exception("当前更新表配置不正确，请检查表名["+update+"]信息！");
        JSONArray fields=new JSONArray();
        execSplitStr(table.getPkKey().getPkColumn(), ";", new SpiltStrCallback(){
            @Override
            public void exec(String id) throws Exception {
                JSONObject dmap=new JSONObject();
                dmap.put("id", id);
                dmap.put("comment", table.getRemarks(id));
                dmap.put("notNull", "true");
                dmap.put("isKey", "true");
                dmap.put("type", table.getDbType(id));
                dmap.put("notNull","true");
                dmap.put("isKey","true");
//                if(fields.size()==0){
//                    String k=table.getPkKey().getPkColumn().replace(";",",");
//                    dmap.put("foreignTab", b.getUpdate());
//                    dmap.put("foreignKey", k);
//                }
                fields.add(dmap);
            }
        });
        String updateTable=update+"_"+billTable.getOrder();
        if(billTable.getOper()!=null){
            JSONObject param=new JSONObject();
            param.put("TABLE_ID", update);
            param.put("TABLE_NAME", update);
            param.put("ID", id);
            param.put("NUM", billTable.getOrder());
            param.put("CREATE_DATE", "SYSDATE");
            param.put("table_time_field","LAST_UPDATED_STAMP");
            switch (billTable.getOper()){
                case "bill":{
                    param.put("LAST_UPDATED_STAMP", "SYSDATE");
                    session.getForUpdate().insertTable("EXE_ACCOUNT_BILL", param);
                    break;
                }
                case "all":{
                    if(billTable.getSeqTime()==null){
                        param.put("LAST_UPDATED_STAMP", "SYSDATE");
                        session.getForUpdate().insertTable("EXE_ACCOUNT_BILL_SEQ", param);
                        session.getForUpdate().insertTable("EXE_ACCOUNT_BILL", param);
                    }
                    else {
                        param.put("LAST_UPDATED_STAMP_NEW", "SYSDATE");
                        param.put("LAST_UPDATED_STAMP", billTable.getSeqTime());
                        session.getForUpdate().saveTable("EXE_ACCOUNT_BILL_SEQ", param);
                        param.put("LAST_UPDATED_STAMP", "SYSDATE");
                        param.remove("LAST_UPDATED_STAMP_NEW");
                        session.getForUpdate().saveTable("EXE_ACCOUNT_BILL", param);
                    }
                    break;
                }
            }
        }
        JSONObject output=step.getAllOutputDef();
        ArrayList<String> flist=billTable.getFields();
        int flen=flist.size();
        for(int f=0; f<flen; f++){
            String key=flist.get(f);
            ConditionStrategy.Field field=(ConditionStrategy.Field) output.get(key);
            String tid=field.getTarget();
            JSONObject map= (JSONObject) condition.getAllField().get(tid);
            if(map==null) throw new Exception("请检查：当前字段["+tid+"]信息不合法，只能设置返回值条件类型中定义过的字段！");
            JSONObject m=new JSONObject();
            m.putAll(map);
            m.put("id", key);
            m.remove("notNull");
            m.remove("isKey");
            fields.add(m);
        }
        if(billTable.isAlter()) session.getForDDL().tableAddColumn(updateTable, fields);
        else session.getForDDL().createTable(updateTable, fields);
        b.getUpdateTable(update).setBillTableName(updateTable);
    }

    public void createBillExtandTable() throws Exception {
        ArrayList<String> klist=bill.getKeylist();
        int len=klist.size();
        for(int i=0; i<len; i++){
            Bill b= (Bill) bill.get(klist.get(i));
            ArrayList<String> list=b.getTableList();
            int jlen=list.size();
            for(int j=0; j<jlen; j++) createBillExtandTable(b, list.get(j));
        }
    }

    public ArrayList<String> getBillKeyList(){
        if(bill==null) return null;
        return bill.getKeylist();
    }

    public Bill getBillFromUpdate(String tableName){
        String id=updateTable.getString(tableName);
        if(id==null) return null;
        return getBill(id);
    }

    public UpdateTable getUpdateTable(String tableName){
        Bill bill=getBillFromUpdate(tableName);
        if(bill==null) return null;
        return bill.getUpdateTable(tableName);
    }

    public void setSession(SqlSession session) {
        this.session = session;
    }
}
